home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 January / macformat-020.iso / Shareware City / Developers / apps.to.go / DTS.StyleChat / AECustom.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-18  |  11.4 KB  |  419 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** File:        AECustom.c
  5. ** Written by:    Eric Soldan
  6. **
  7. ** Copyright © 1990-1991 Apple Computer, Inc.
  8. ** All rights reserved.
  9. */
  10.  
  11.  
  12.  
  13. /*****************************************************************************/
  14.  
  15.  
  16.  
  17. #include "App.h"            /* Get the application includes/typedefs, etc.    */
  18. #include "App.defs.h"        /* Get various application definitions.            */
  19. #include "App.protos.h"        /* Get the prototypes for application.            */
  20.  
  21. #ifndef __ERRORS__
  22. #include <Errors.h>
  23. #endif
  24.  
  25. #ifndef __TEXTEDITCONTROL__
  26. #include "TextEditControl.h"
  27. #endif
  28.  
  29. #ifndef __UTILITIES__
  30. #include "Utilities.h"
  31. #endif
  32.  
  33.  
  34.  
  35. /*****************************************************************************/
  36.  
  37.  
  38.  
  39. extern Boolean        gHasAppleEvents;
  40.     /* This is defined and initialized by the DTS.Lib..framework file AERequired.c.
  41.     ** This means that InitRequiredAppleEvents must be called prior to calling
  42.     ** InitConnectAppleEvents (a DTS.Lib..framework function), or before calling
  43.     ** InitCustomAppleEvents (a DTS.StyleChat function). */
  44.  
  45.  
  46. static pascal OSErr        ReceiveMessage(AppleEvent *message, AppleEvent *reply, long refcon);
  47.  
  48.  
  49.  
  50. /*****************************************************************************/
  51.  
  52.  
  53.  
  54. static AEHandler keywordsToInstall[] = {
  55.     { kCustomEventClass, keyAppMessage, (AEEventHandlerProcPtr)ReceiveMessage, nil }
  56. };        /* These are the custom AppleEvents. */
  57.  
  58. #define kNumKeywords (sizeof(keywordsToInstall) / sizeof(AEHandler))
  59.  
  60.  
  61.  
  62. /*****************************************************************************/
  63. /*****************************************************************************/
  64.  
  65.  
  66.  
  67. /* Install our custom AppleEvents.  This is done in addition to installing
  68. ** the required AppleEvents.  InitAppleEvents, which installs the required
  69. ** AppleEvents, must be called first, since it sets up some global values. */
  70.  
  71. #pragma segment AppleEvents
  72. void    InitCustomAppleEvents(void)
  73. {
  74.     OSErr    err;
  75.     short    i;
  76.  
  77.     if (gHasAppleEvents) {
  78.         for (i = 0; i < kNumKeywords; ++i) {
  79.  
  80.             if (!keywordsToInstall[i].theUPP)
  81.                 keywordsToInstall[i].theUPP = NewAEEventHandlerProc(keywordsToInstall[i].theHandler);
  82.  
  83.             err = AEInstallEventHandler(
  84.                 keywordsToInstall[i].theEventClass,    /* What class to install.  */
  85.                 keywordsToInstall[i].theEventID,    /* Keywords to install.    */
  86.                 keywordsToInstall[i].theUPP,        /* The AppleEvent handler. */
  87.                 0L,                                    /* Unused refcon.           */
  88.                 false                                /* Only for our app.       */
  89.             );
  90.  
  91.             if (err) {
  92.                 HCenteredAlert(rErrorAlert, nil, gAlertFilterUPP);
  93.                 return;
  94.             }
  95.         }
  96.     }
  97. }
  98.  
  99.  
  100.  
  101. /*****************************************************************************/
  102.  
  103.  
  104.  
  105. /* Send some type of message to the application we are connected to.  Most of the
  106. ** targeting information is the same for various different messages.  Given this,
  107. ** this function builds an AppleEvent, adds the common information to the AppleEvent,
  108. ** and then switches for the various different message types.  A similar factoring
  109. ** process is done at the receiving end. */
  110.  
  111. #pragma segment AppleEvents
  112. OSErr    SendMessage(FileRecHndl frHndl, short messageType)
  113. {
  114.     AEAddressDesc    remoteLoc;
  115.     OSErr            err;
  116.     AppleEvent        theAevt, reply;
  117.     long            windTag[2];
  118.     short            i;
  119.     WindowPtr        oldPort;
  120.     TEHandle        te;
  121.     char            hstate;
  122.     Handle            hText;
  123.     StScrpHandle    styl;
  124.     long            size;
  125.  
  126.     remoteLoc = (*frHndl)->connect.remoteLoc;
  127.  
  128.     if (!(*frHndl)->connect.connected) {
  129.         if (remoteLoc.dataHandle) {
  130.             AEDisposeDesc(&remoteLoc);
  131.             (*frHndl)->connect.remoteLoc.dataHandle = nil;
  132.         }
  133.         return(noErr);
  134.     }
  135.  
  136.     oldPort = SetFilePort(frHndl);
  137.  
  138.     theAevt.dataHandle = reply.dataHandle = nil;
  139.         /* Make sure disposing of the descriptors is okay in all cases. */
  140.         /* Even though the AppleEvent manager nils out the handle upon failure,
  141.         ** the below code doesn't necessarily call the AppleEvent manager for each
  142.         ** descriptor.  By etting them to nil here, this allows us to just try to
  143.         ** dispose of the descriptors at the bottom of the function. */
  144.  
  145.     err = AECreateAppleEvent(        /* CREATE EMPTY APPLEEVENT.     */
  146.         kCustomEventClass,            /* Event class.                 */
  147.         typeAppMessage,                /* Event ID.                 */
  148.         &remoteLoc,                    /* Address of receiving app. */
  149.         kAutoGenerateReturnID,        /* This value causes the     */
  150.                                     /* AppleEvent manager to     */
  151.                                     /* assign a return ID that     */
  152.                                     /* is unique to the session. */
  153.         kAnyTransactionID,            /* Ignore transaction ID.     */
  154.         &theAevt                    /* Location of event.         */
  155.     );
  156.  
  157.     if (!err)            /* Say what the message is. */
  158.         AEPutParamPtr(&theAevt,keyDirectObject, typeShortInteger, (Ptr)&messageType, sizeof(short));
  159.  
  160.     if (!err) {            /* Say what window message is for. */
  161.         for (i = 0; i < 2; ++i) windTag[i] = (*frHndl)->connect.windowTag[i];
  162.         AEPutParamPtr(&theAevt, keyWindowTag, typeDoubleLong, (Ptr)windTag, 2 * sizeof(long));
  163.     }
  164.  
  165.     /* The stuff that applies to all messages is now done.  Now specifically
  166.     ** handle all the different message types. */
  167.  
  168.     if (!err) {
  169.         switch (messageType) {
  170.  
  171.             case kDisconnectMssg:
  172.                     /* All the information we need is already in the AppleEvent. */
  173.                 break;
  174.  
  175.             case kTextMssg:
  176.                 te     = (*frHndl)->d.doc.outBox;
  177.                 hText  = (*te)->hText;
  178.                 hstate = LockHandleHigh(hText);
  179.                 size   = (*te)->teLength;
  180.                 err = AEPutParamPtr(
  181.                     &theAevt,
  182.                     keyAppMessage,
  183.                     typeTextMessage,
  184.                     *hText,
  185.                     size
  186.                 );
  187.                 HSetState(hText, hstate);
  188.                 break;
  189.  
  190.             case kStylMssg:
  191.                 styl = CTEGetFullStylScrap((*frHndl)->d.doc.outBox);
  192.                 if (styl) {
  193.                     LockHandleHigh((Handle)styl);
  194.                     size = GetHandleSize((Handle)styl);
  195.                     err = AEPutParamPtr(
  196.                         &theAevt,
  197.                         keyStylMessage,
  198.                         typeStylMessage,
  199.                         (Ptr)*styl,
  200.                         size
  201.                     );
  202.                     DisposeHandle((Handle)styl);
  203.                 }
  204.                 break;
  205.         }
  206.     }
  207.  
  208.     if (!err) {        /* If everything looks good... */
  209.         err = AESend(                    /* SEND APPLEEVENT.                */
  210.             &theAevt,                    /* Our Apple Event to send.        */
  211.             &reply,                        /* We may have a reply.            */
  212.             kAENoReply,                    /* Don't wait for reply.        */
  213.             kAENormalPriority,            /* App. send priority.            */
  214.             0,                            /* We aren't waiting.            */
  215.             nil,                        /* No wait, no filter.            */
  216.             nil                            /* EventFilterProcPtr.            */
  217.         );
  218.     }
  219.  
  220.     if (!err) {
  221.         switch (messageType) {
  222.             case kDisconnectMssg:
  223.                 (*frHndl)->connect.connected            = false;
  224.                 (*frHndl)->connect.remoteLoc.dataHandle = nil;
  225.                 (*frHndl)->connect.remotePath[0]        = 0;
  226.                 break;
  227.             case kTextMssg:
  228.                 CTESetSelect(0, (*te)->teLength, te);
  229.                     /* Select all the text so entering the next message is more convenient. */
  230.                 break;
  231.         }
  232.     }
  233.  
  234.     AEDisposeDesc(&theAevt);
  235.     AEDisposeDesc(&reply);
  236.         /* Dispose of the descriptors, created or not.  If not created, no harm done by calling. */
  237.  
  238.     SetPort(oldPort);
  239.     return(err);
  240. }
  241.  
  242.  
  243.  
  244. /*****************************************************************************/
  245.  
  246.  
  247.  
  248. #pragma segment AppleEvents
  249. static pascal OSErr    ReceiveMessage(AppleEvent *message, AppleEvent *reply, long refcon)
  250. {
  251. #ifndef __MWERKS__
  252. #pragma unused (reply, refcon)
  253. #endif
  254.  
  255.     OSErr            err;
  256.     short            messageType;
  257.     WindowPtr        window;
  258.     FileRecHndl        frHndl;
  259.     DescType        actualType;
  260.     long            actualSize, windTag[2];
  261.     AEAddressDesc    remoteLoc;
  262.     Handle            mssgData;
  263.     StScrpHandle    stylData;
  264.     TEHandle        te;
  265.     char            hstate;
  266.     long            mssgSize, stylSize;
  267.     ControlHandle    ctl;
  268.  
  269.     err = AEGetParamPtr(        /* GET THE MESSAGE TYPE.     */
  270.         message,                /* The AppleEvent.              */
  271.         keyDirectObject,        /* AEKeyword                 */
  272.         typeShortInteger,        /* Desired type.             */
  273.         &actualType,            /* Type code.                 */
  274.         (Ptr)&messageType,        /* Pointer to area for data. */ 
  275.         2 * sizeof(long),        /* Size of data area.         */
  276.         &actualSize                /* Returned size of data.     */
  277.     );
  278.  
  279.     if (!err) {
  280.         err = AEGetParamPtr(        /* GET WINDOW MESSAGE IS FOR. */
  281.             message,                /* The AppleEvent.               */
  282.             keyWindowTag,            /* AEKeyword                  */
  283.             typeDoubleLong,            /* Desired type.              */
  284.             &actualType,            /* Type code.                  */
  285.             (Ptr)windTag,            /* Pointer to area for data.  */ 
  286.             2 * sizeof(long),        /* Size of data area.          */
  287.             &actualSize                /* Returned size of data.      */
  288.         );
  289.     }
  290.  
  291.     if (!err) {            /* See if the requested window exists... */
  292.         window = GetAEWindow(windTag[1], windTag[0]);
  293.         if (window) {
  294.             frHndl = (FileRecHndl)GetWRefCon(window);
  295.                 /* The window still exists... */
  296.         }
  297.         else
  298.             err = userCanceledErr;
  299.                 /* User (or computer) canceled connection by disconnecting improperly. */
  300.     }
  301.  
  302.     if (!err) {        /* If everything is cool, then do the specific task... */
  303.  
  304.         switch(messageType) {
  305.  
  306.             case kDisconnectMssg:
  307.                 remoteLoc = (*frHndl)->connect.remoteLoc;
  308.                 AEDisposeDesc(&remoteLoc);
  309.                 (*frHndl)->connect.connected            = false;
  310.                 (*frHndl)->connect.remoteLoc.dataHandle = nil;
  311.                 (*frHndl)->connect.remotePath[0]        = 0;
  312.                 CNum2Ctl(window, 1020, &ctl);
  313.                 (*ctl)->contrlVis = false;
  314.                 BeginFrame(window);
  315.                 CNum2Ctl(window, 1010, &ctl);
  316.                 ShowStyledControl(ctl);
  317.                 CNum2Ctl(window, 1000, &ctl);
  318.                 (*ctl)->contrlVis = false;
  319.                 CNum2Ctl(window, 1002, &ctl);
  320.                 DoDraw1Control(ctl, false);
  321.                 EndFrame(window);
  322.                 break;
  323.  
  324.             case kTextMssg:
  325.                 if (!err) {        /* Determine the size of the data... */
  326.                     err = AEGetParamPtr(
  327.                         message,                /* The AppleEvent.              */
  328.                         keyAppMessage,            /* AEKeyword                 */
  329.                         typeTextMessage,        /* Desired type.             */
  330.                         &actualType,            /* Type code.                 */
  331.                         nil,                    /* Pointer to area for data. */ 
  332.                         0,                        /* Size of data area.         */
  333.                         &mssgSize                /* Returned size of data.     */
  334.                     );
  335.                 }
  336.                 mssgData = nil;
  337.                 if (!err) {        /* Get the data... */
  338.                     mssgData = NewHandle(mssgSize);
  339.                     if (mssgData) {
  340.                         hstate = LockHandleHigh(mssgData);
  341.                         err = AEGetParamPtr(
  342.                             message,                /* The AppleEvent.              */
  343.                             keyAppMessage,            /* AEKeyword                 */
  344.                             typeTextMessage,        /* Desired type.             */
  345.                             &actualType,            /* Type code.                 */
  346.                             *mssgData,                /* Pointer to area for data. */ 
  347.                             mssgSize,                /* Size of data area.         */
  348.                             &actualSize                /* Returned size of data.     */
  349.                         );
  350.                         HSetState(mssgData, hstate);
  351.                     }
  352.                     else err = memFullErr;
  353.                 }
  354.                 if (!err) {
  355.                     BeginContent(window);
  356.                         /* Clip out all but content portion of the window. */
  357.  
  358.                     te       = (*frHndl)->d.doc.inBox;
  359.                     stylData = (*frHndl)->d.doc.textStyl;
  360.                     mssgData = CTESwapText(te, mssgData, stylData, true);
  361.                     if (stylData) {
  362.                         DisposeHandle((Handle)stylData);
  363.                         (*frHndl)->d.doc.textStyl = nil;
  364.                     }
  365.  
  366.                     EndContent(window);
  367.                         /* Fix the window back to normal. */
  368.                 }
  369.  
  370.                 if (mssgData)
  371.                     DisposeHandle(mssgData);
  372.  
  373.                 if (!err)
  374.                     NotifyUser();
  375.  
  376.                 break;
  377.  
  378.             case kStylMssg:
  379.                 if (!err) {        /* Determine the size of the data... */
  380.                     err = AEGetParamPtr(
  381.                         message,                /* The AppleEvent.              */
  382.                         keyStylMessage,            /* AEKeyword                 */
  383.                         typeStylMessage,        /* Desired type.             */
  384.                         &actualType,            /* Type code.                 */
  385.                         nil,                    /* Pointer to area for data. */ 
  386.                         0,                        /* Size of data area.         */
  387.                         &stylSize                /* Returned size of data.     */
  388.                     );
  389.                 }
  390.                 stylData = nil;
  391.                 if (!err) {        /* Get the data... */
  392.                     stylData = (StScrpHandle)NewHandle(stylSize);
  393.                     if (stylData) {
  394.                         hstate = LockHandleHigh((Handle)stylData);
  395.                         err = AEGetParamPtr(
  396.                             message,                /* The AppleEvent.              */
  397.                             keyStylMessage,            /* AEKeyword                 */
  398.                             typeStylMessage,        /* Desired type.             */
  399.                             &actualType,            /* Type code.                 */
  400.                             (Ptr)*stylData,            /* Pointer to area for data. */ 
  401.                             stylSize,                /* Size of data area.         */
  402.                             &actualSize                /* Returned size of data.     */
  403.                         );
  404.                         HSetState((Handle)stylData, hstate);
  405.                         (*frHndl)->d.doc.textStyl = stylData;
  406.                     }
  407.                     else err = memFullErr;
  408.                 }
  409.                 break;
  410.  
  411.         }
  412.     }
  413.  
  414.     return(err);
  415. }
  416.  
  417.  
  418.  
  419.